package main

import (
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

// Asset 定义资产结构
type Asset struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Info  string `json:"info"`
	Owner string `json:"owner"`
}

// SimpleAssetChaincode 链码结构体
type SimpleAssetChaincode struct {
}

// Init 链码初始化方法
func (t *SimpleAssetChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
	return shim.Success(nil)
}

// Invoke 链码调用方法
func (t *SimpleAssetChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	fn, args := stub.GetFunctionAndParameters()
	var result string
	var err error
	if fn == "createAsset" {
		result, err = createAsset(stub, args)
	} else if fn == "transferAsset" {
		result, err = transferAsset(stub, args)
	} else {
		return shim.Error("未知函数调用")
	}
	if err != nil {
		return shim.Error(err.Error())
	}
	return shim.Success([]byte(result))
}

// createAsset 创建资产
func createAsset(stub shim.ChaincodeStubInterface, args []string) (string, error) {
	if len(args) != 4 {
		return "", fmt.Errorf("需要4个参数：资产编号、资产名、资产信息、资产所有者")
	}
	id := args[0]
	name := args[1]
	info := args[2]
	owner := args[3]

	asset := Asset{
		ID:    id,
		Name:  name,
		Info:  info,
		Owner: owner,
	}
	assetJSON, err := json.Marshal(asset)
	if err != nil {
		return "", err
	}
	err = stub.PutState(id, assetJSON)
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("成功创建资产：%s", id), nil
}

// transferAsset 转移资产
func transferAsset(stub shim.ChaincodeStubInterface, args []string) (string, error) {
	if len(args) != 2 {
		return "", fmt.Errorf("需要2个参数：资产编号、新的资产所有者")
	}
	id := args[0]
	newOwner := args[1]

	assetJSON, err := stub.GetState(id)
	if err != nil {
		return "", fmt.Errorf("获取资产信息失败：%s", err.Error())
	}
	if assetJSON == nil {
		return "", fmt.Errorf("资产 %s 不存在", id)
	}

	var asset Asset
	err = json.Unmarshal(assetJSON, &asset)
	if err != nil {
		return "", err
	}

	asset.Owner = newOwner
	newAssetJSON, err := json.Marshal(asset)
	if err != nil {
		return "", err
	}
	err = stub.PutState(id, newAssetJSON)
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("成功将资产 %s 转移给 %s", id, newOwner), nil
}

func main() {
	err := shim.Start(new(SimpleAssetChaincode))
	if err != nil {
		fmt.Printf("启动链码失败: %s", err)
	}
}
